package faceBook;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.sql.Date;

import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONString;

import twss.DataConnection;
import twss.DataObject;

/**
 * The Class User.
 */
public class User implements DataObject, JSONString
{

    /** The ID. */
    private long ID;
    
    /** The email. */
    private String email;
    
    /** The access token. */
    private String accessToken;
    
    /** The expire time. */
    private long expireTime;
    
    /** The birthday. */
    private Date birthday;
    
    /** The friends. */
    private ArrayList<User> friends = null;

    /**
     * Instantiates a new user.
     */
    private User()
    {
    }

    /**
     * Instantiates a new user.
     * 
     * @param id
     *            the id
     */
    public User(long id)
    {
        ID = id;
        load();
    }

    /**
     * Gets the email.
     * 
     * @return the email
     */
    public String getEmail()
    {
        return email;
    }

    /**
     * Sets the email.
     * 
     * @param Email
     *            the new email
     */
    public void setEmail(String Email)
    {
        this.email = Email;
    }

    /**
     * Gets the access token.
     * 
     * @return the access token
     */
    public String getAccessToken()
    {
        return accessToken;
    }

    /**
     * Sets the access token.
     * 
     * @param AccessToken
     *            the new access token
     */
    public void setAccessToken(String AccessToken)
    {
        this.accessToken = AccessToken;
    }

    /**
     * Gets the expire time.
     * 
     * @return the expire time
     */
    public long getExpireTime()
    {
        return expireTime;
    }

    /**
     * Sets the expire time.
     * 
     * @param ExpireTime
     *            the new expire time
     */
    public void setExpireTime(long ExpireTime)
    {
        this.expireTime = ExpireTime;
    }

    /**
     * Gets the birthday.
     * 
     * @return the birthday
     */
    public Date getBirthday()
    {
        return birthday;
    }

    /**
     * Sets the birthday.
     * 
     * @param Birthday
     *            the new birthday
     */
    public void setBirthday(Date Birthday)
    {
        this.birthday = Birthday;
    }

    /**
     * Gets the iD.
     * 
     * @return the iD
     */
    public long getID()
    {
        return ID;
    }

    /* (non-Javadoc)
     * @see org.json.JSONString#toJSONString()
     */
    @Override
    public String toJSONString()
    {
        JSONObject JO = new JSONObject();
        try
        {
            JO.put("id", ID);
            JO.put("email", email);
            JO.put("accessToken", accessToken);
            JO.put("expireTime", expireTime);
            JO.put("birthday", birthday);
        } catch (JSONException e)
        {
            // Do Nothing
        }
        return JO.toString();
    }

    /* (non-Javadoc)
     * @see foxtrotbravo.DataObject#save()
     */
    @Override
    public boolean save()
    {
        try
        {
            if (ID != 0)
            {
                return update();
            }
            return insert();
        } catch (SQLException e)
        {
            e.printStackTrace();
        }
        return false;
    }

    /* (non-Javadoc)
     * @see foxtrotbravo.DataObject#load()
     */
    @Override
    public boolean load()
    {
        try
        {
            if (DataConnection.connect())
            {
                String statement = "select email, accessToken, expireTime, birthday from user where id = ?";
                PreparedStatement stmt = DataConnection.getConnection()
                        .prepareStatement(statement);
                stmt.setLong(1, ID);
                ResultSet results = stmt.executeQuery();
                if (results.next())
                {
                    email = results.getString("email");
                    accessToken = results.getString("accessToken");
                    expireTime = results.getLong("expireTime");
                    birthday = results.getDate("birthday");
                    return true;
                }
            }
        } catch (SQLException e)
        {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Gets the friends.
     * 
     * @return the friends
     */
    public ArrayList<User> getFriends()
    {
        if (friends == null)
        {
            try
            {
                if (DataConnection.connect())
                {
                    String statement = "select id, email, accessToken, expireTime, birthday from user where id in (select friend from user where user = ?)";
                    PreparedStatement stmt = DataConnection.getConnection()
                            .prepareStatement(statement);
                    stmt.setLong(1, ID);
                    ResultSet results = stmt.executeQuery();
                    friends = new ArrayList<User>();
                    while (results.next())
                    {
                        User friend = new User();
                        friend.ID = results.getLong("id");
                        friend.email = results.getString("email");
                        friend.accessToken = results.getString("accessToken");
                        friend.expireTime = results.getLong("expireTime");
                        friend.birthday = results.getDate("birthday");
                        friends.add(friend);
                    }
                    return friends;
                }
            } catch (SQLException e)
            {
                e.printStackTrace();
            }
        }
        return friends;
    }

    /* (non-Javadoc)
     * @see foxtrotbravo.DataObject#delete()
     */
    @Override
    public boolean delete()
    {
        try
        {
            if (DataConnection.connect())
            {
                String statement = "delete from user where id = ?";
                PreparedStatement stmt = DataConnection.getConnection()
                        .prepareStatement(statement);
                stmt.setLong(1, ID);
                int success = 2;
                success = stmt.executeUpdate();
                return success == 1;
            }
        } catch (SQLException e)
        {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * Update.
     * 
     * @return true, if successful
     * @throws SQLException
     *             the SQL exception
     */
    private boolean update() throws SQLException
    {
        if (DataConnection.connect())
        {
            String statement = "update user set email = ?, accessToken = ?, expireTime = ?, birthday = ? where id = ?";
            PreparedStatement stmt = DataConnection.getConnection()
                    .prepareStatement(statement);
            stmt.setString(1, email);
            stmt.setString(2, accessToken);
            stmt.setLong(3, expireTime);
            stmt.setDate(4, birthday);
            stmt.setLong(5, ID);
            int success = 2;
            stmt.executeUpdate();
            return success == 1;
        }
        return false;
    }

    /**
     * Insert.
     * 
     * @return true, if successful
     * @throws SQLException
     *             the sQL exception
     */
    private boolean insert() throws SQLException
    {
        if (DataConnection.connect())
        {
            String statement = "INSERT INTO user (email, accessToken, expireTime, birthday) VALUES ( ?, ?, ?, ? )";
            PreparedStatement stmt = DataConnection.getConnection()
                    .prepareStatement(statement,
                            Statement.RETURN_GENERATED_KEYS);
            stmt.setString(1, email);
            stmt.setString(2, accessToken);
            stmt.setLong(3, expireTime);
            stmt.setDate(4, birthday);
            int success = 2;
            stmt.executeUpdate();
            ResultSet key = stmt.getGeneratedKeys();
            if (key.next())
            {
                ID = key.getLong(1);
            }
            return success == 1;
        }
        return false;
    }

}
